<?php

namespace app\company\controller;

use app\common\controller\CompanyController;
use app\common\enum\purchase\OrderStatus;
use app\common\enum\purchase\OrderStatus as PurchaseStatus;
use app\common\enum\purchase\OrderType;
use app\common\exception\BaseException;
use app\common\model\CompanyWarehouse;
use app\common\model\DealerGoodsSpec;
use app\common\model\DealerGoods;
use app\common\model\DealerGoodsCate;
use app\common\service\annotation\ControllerAnnotation;
use app\common\service\annotation\NodeAnnotation;
use app\company\model\CompanyUser;
use app\company\model\DealerOrder;
use app\company\model\DealerOrderDetail;
use app\company\model\InStorageDetail;
use app\Request;
use think\App;
use think\response\Json;

/**
 * @ControllerAnnotation(title="采购管理")
 */
class PurchaseOrder extends CompanyController
{
    public function __construct(App $app)
    {
        parent::__construct($app);
        $this->model = new DealerOrder();
    }

    public function list(): Json
    {
        $get = $this->request->get();
        [, $where] = $this->buildSearchParams($get);
        if (empty($get['order_type'])) {
            $where[] = ['id', '<', 0];
        } else {
            $where[] = ['order_type', '=', $get['order_type']];
        }
        $list = $this->model->with([
                                           'detail'    => function ($query)
                                           {
                                               $query->with([
                                                                    'goods' => function ($query)
                                                                    {
                                                                        $query->field('id,name,image')->withTrashed();
                                                                    },
                                                                    'spec'  => function ($query)
                                                                    {
                                                                        $query->field('id,name,unit,image')
                                                                              ->withTrashed();
                                                                    },
                                                            ]);
                                           },
                                           'company'   => function ($query)
                                           {
                                               $query->field(['id', 'name']);
                                           },
                                           'dealer'    => function ($query)
                                           {
                                               $query->field(['id', 'name']);
                                           },
                                           'warehouse' => function ($query)
                                           {
                                               $query->field(['id', 'name']);
                                           },
                                           'supplier'  => function ($query)
                                           {
                                               $query->field('id,name,short_name');
                                           }
                                   ])->where($this->defaultWhere)
                            ->order($this->sort)
                            ->where($where)
                            ->paginate($get['limit'] ?? 15)->each(function ($item)
                {
                    $item->creator = (new CompanyUser())->where('id', $item->creator_id)->value('username') ?? '无';
                    $item->auditor = (new CompanyUser())->where('id', $item->auditor_id)->value('username') ?? '无';
                });
        return $this->success($list);
    }

    /**
     * @NodeAnnotation(title="新增采购或采退订单")
     */
    public function add(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        $this->sceneValidate($post, 'add');
        if (empty($post['order_type'])) return $this->error('缺少新增单据类型，请查看参数！');
        $wareId = (new CompanyWarehouse())->where('company_id', $this->companyId)->value('id');
        if (empty($wareId)) return $this->error('请先创建仓库！');
        $post['company_id']           = $this->companyId;
        $post['company_user_id']      = $this->uid;
        $post['pay_time']             = empty($post['pay_time']) ? time() : strtotime($post['pay_time']);
        $post['order_time']           = empty($post['order_time']) ? time() : strtotime($post['order_time']);
        $post['order_no']             = $post['order_type'] == OrderType::CG ? generateOrderNo('CG') :
                generateOrderNo('CT');
        $post['company_warehouse_id'] = $wareId;
        $post['order_status']         = OrderStatus::WAIT;
        $post['creator_id']           = $this->uid;
        try {
            $this->model->transaction(function () use ($post)
            {
                $goods_model = new DealerGoods();
                $detail      = json_decode($post['detail'], true);
                if (empty($detail)) throw new BaseException('请选择商品');

                foreach ($detail as $k => &$vo) {
                    $goods = (new DealerGoods())->find($vo['dealer_goods_id']);
                    if (!$goods) throw new BaseException(['message' => '商品不存在']);
                    $spec = $goods->spec()->where('id', $vo['dealer_goods_spec_id'])->field('id')->find();
                    if (!$spec) throw new BaseException(['message' => '规格不存在']);
                    $vo['purchase_total_price'] = $vo['purchase_price'] * $vo['num'];
                    $vo['company_warehouse_id'] = $post['company_warehouse_id'];
                    $vo['real_num']             = $vo['num'];
                    $vo['company_id']           = $post['company_id'];
                    $vo['order_type']           = $post['order_type'];
                    $vo['dealer_id']            = $post['dealer_id'];
                    //查询商品分类id
                    $cate_id = $goods_model->where('id', $vo['dealer_goods_id'])->value('cate_id');

                }
                $post['pay_amount'] = $post['order_amount'] = array_sum(array_column($detail, 'purchase_total_price'));
                $save               = $this->model->save($post);
                if (!$save) throw new BaseException(['message' => '新增失败']);
                $this->model->detail()->saveAll($detail);


            });
        } catch (\Exception $e) {
            return $this->error('新增失败:' . $e->getMessage());
        }
        return $this->success('新增成功');
    }

    /**
     * @NodeAnnotation(title="修改采购单")
     * @param Request $request
     * @return Json
     * @throws BaseException
     */
    public function modify(Request $request): Json
    {
        $this->checkPost();
        $post = $request->post();
        try {
            // 修改的是审核状态字段
            if ($post['field'] == 'order_status') {
                // 获取详情
                $detail          = (new DealerOrderDetail())->where('dealer_order_id', $post['id'])->select();
                $dealerOrderInfo = $this->model->find($post['id']);
                if ($post['value'] == OrderStatus::PASS) {
                    // 修改的是审核成功
                    // 2024.12.06 增加采退修改库存，创建采退单时只扣减售卖库存，确认出库后再扣减库内库存
                    if ($dealerOrderInfo->order_type == OrderType::CT) {
                        foreach ($detail as $vo) {
                            $goods = (new DealerGoods())->find($vo['dealer_goods_id']);
                            if (!$goods) throw new BaseException(['message' => '商品不存在']);
                            $spec = $goods->spec()->find($vo['dealer_goods_spec_id']);
                            if (!$spec) throw new BaseException(['message' => '规格不存在']);
                            if ($goods->sales_stock < $vo['num'] * $spec['ratio']) throw new BaseException(['message' => '库存不足，无法采退']);
                            $goods->dec('sales_stock', $vo['num'] * $spec['ratio'])->save();
                        }
                    }
                } elseif ($post['value'] == OrderStatus::REFUSE) {
                    // 修改的是驳回
                }
                $this->model->where('id', $post['id'])
                            ->update(['order_status' => $post['value'], 'auditor_id' => $this->uid]);
            }
        } catch (\Exception $e) {
            return $this->error('修改失败:' . $e->getMessage());
        }
        return $this->success('修改成功');
    }

    /**
     * @NodeAnnotation(title="签收入库")
     */
    public function putIn(Request $request): Json
    {
        /**
         * @NodeAnnotation(title="签收入库")
         */
        $post = $request->post();
        $rule = [
                'id|采购单'           => 'require',
                'detail|签收入库详情' => 'require',
        ];
        $this->validate($post, $rule);
        try {
            $this->model->transaction(function () use ($post)
            {
                $info = $this->model->find($post['id']);
                if (!$info) throw new BaseException(['message' => '采购单不存在']);
                // 更新状态
                $info->save(['order_status' => PurchaseStatus::PUT_IN]);
                $detail = json_decode($post['detail'], true);
                array_walk($detail, function ($vo) use ($info)
                {
                    $orderDetail = $info->detail()->withTrashed()->find($vo['id']);
                    if (!$orderDetail) throw new BaseException(['message' => '采购单详情不存在']);
                    // 规格比例值
                    $ratio = $orderDetail->spec()->value('ratio');
                    // 最小规格数量
                    $minNum = $vo['real_num'] * $ratio;
                    // 查询经销商商品信息
                    $dealerGoods = $orderDetail->goods()->find();
                    if (!$dealerGoods) throw new BaseException(['message' => '经销商商品不存在']);
                    if (isset($vo['batch'])) {
                        // 格式化批次信息
                        $batchInfo = is_string($vo['batch']) ? json_decode($vo['batch'], true) : $vo['batch'];
                        foreach ($batchInfo as &$item) {
                            $item['num'] = $item['num'] * $ratio;
                        }
                        $batch = $batchInfo;
                        if($dealerGoods->batch) {
                            // 合并批次信息
                            $goodsBatch = json_decode($dealerGoods->batch, true);
                            $batchArr = array_merge($goodsBatch, $batchInfo);
                            // 合计签收数量
                            $batch_num = array_sum(array_column($batchInfo, 'num'));
                            if ($batch_num != $minNum) throw new BaseException(['message' => '签收数量与批次数量不一致']);
                            // 按时间排序
                            $result = array_reduce($batchArr, function($carry, $item) {
                                $key = $item['time'];
                                if (!isset($carry[$key])) {
                                    $carry[$key] = $item;
                                } else {
                                    $carry[$key]['num'] = strval(intval($carry[$key]['num']) + intval($item['num']));
                                }
                                return $carry;
                            }, []);
                            // 将关联数组转换为索引数组
                            $batch = array_values($result);
                        }
                        // 更新批次信息
                        $dealerGoods->batch = json_encode($batch);
                    }else{
                        throw new BaseException(['message' => '请先选择商品批次']);
                    }
                    $dealerGoods->sales_stock     += $minNum;
                    $dealerGoods->warehouse_stock += $minNum;
                    $dealerGoods->save();
                    // 更新商品实际签收数量
                    $orderDetail->save(['real_num' => $vo['real_num']]);
                });
            });
        } catch (\Exception $e) {
            return $this->error('签收入库失败:' . $e->getMessage());
        }
        return $this->success('签收入库成功');
    }
}